//
//  FXTimer.swift
//  FXEvent
//
//  Created by JY_NEW on 2021/11/23.
//

import Foundation

open class FXTimer: FXEvent<Void> {
    ///间隔，默认1秒
    open var interval: TimeInterval {
        didSet {
            if self.interval != oldValue {
                self.refreshConfig()
            }
        }
    }
    ///能接受的最大误差
    open var leeway: DispatchTimeInterval {
        didSet {
            if self.leeway != oldValue {
                self.refreshConfig()
            }
        }
    }
    ///计时器所在队列
    open var queue: DispatchQueue {
        didSet {
            if self.queue != oldValue {
                self.refreshConfig()
            }
        }
    }
    ///使用间隔初始化
    public init(interval:TimeInterval = 1, leeway: DispatchTimeInterval = .seconds(0), queue: DispatchQueue = .global()) {
        self.interval = interval
        self.leeway = leeway
        self.queue = queue
        super.init()
    }
    ///是否在开启时马上执行
    public var isExecuteWhenStartup = false
    ///是否在无可处理时自动停止，若是启用了该选项，则在自动停止而非手动停止后可在添加处理后自动启动，但若是自动停止后调用过stop方法则不会再自动启动
    public var isAutoStopWhenEmpty = false
    ///添加处理的时候自动启动
    public var isAutoStartWhenHandled = false
    ///最后执行的时间
    public private(set) var lastSendTime: Date? = nil
    
    private var timer: DispatchSourceTimer? = nil
    private var isAutoStoping = false
    
    //是否正在计时,计时中也可往里面加处理
    public private(set) var isRunning: Bool = false
    //开始
    open func start() {
        if !self.isRunning {
            if self.tryAutoStop() {
                return
            }
            if self.isExecuteWhenStartup {
                self.sendActions()
            }
            self.startTimer()
        }
    }
    //结束
    open func stop() {
        self.isAutoStoping = false
        if self.isRunning {
            self.stopTimer()
        }
    }
    func startTimer() {
        if self.timer == nil {
            self.timer = self.createTimer()
        }
        self.timer?.resume()
        self.isRunning = true
    }
    func stopTimer() {
        self.timer?.suspend()
        self.isRunning = false
    }
    func cancelTimer() {
        self.releaseTimer()
        self.isRunning = false
    }
    func createTimer() -> DispatchSourceTimer {
        let timer = DispatchSource.makeTimerSource(flags: [], queue: self.queue)
        timer.schedule(deadline: .now() + self.interval, repeating: self.interval, leeway: self.leeway)
        timer.setEventHandler(handler: { [weak self] in
            self?.run()
        })
        return timer
    }
    func releaseTimer() {
        if let t = timer {
            if !self.isRunning {
                t.resume()
            }
            t.cancel()
            self.timer = nil
        }
    }
    /// 刷新配置
    func refreshConfig() {
        self.releaseTimer()
        if self.isRunning {
            self.timer = self.createTimer()
            self.timer?.resume()
        }
    }
    func run() {
        if !self.tryAutoStop() {
            self.sendActions()
        }
    }
    @discardableResult
    func tryAutoStop() -> Bool {
        if self.isAutoStopWhenEmpty && self.isEmpty {
            self.stop()
            self.isAutoStoping = true
            return true
        }
        return false
    }
    @discardableResult
    func tryAutoStart() -> Bool {
        if self.isRunning {
            return false
        }
        if (self.isAutoStartWhenHandled || self.isAutoStoping) && !self.isEmpty {
            //马上执行
            if self.isExecuteWhenStartup {
                self.sendActions()
            }
            self.startTimer()
            self.isAutoStoping = false
            return true
        }
        return false
    }
    func whenAdd() {
        self.tryAutoStart()
    }
    func whenRemove() {
        self.tryAutoStop()
    }
    open override func addTarget(_ target: AnyObject, action: Selector) {
        super.addTarget(target, action: action)
        self.whenAdd()
    }
    open override func addBlock(_ block: @escaping (()) -> Void) {
        super.addBlock(block)
        self.whenAdd()
    }
    open override func addBlock(_ identifier: String, block: @escaping (()) -> Void) {
        super.addBlock(identifier, block: block)
        self.whenAdd()
    }
    open override func removeTarget(_ target: AnyObject, action: Selector) {
        super.removeTarget(target, action: action)
        self.whenRemove()
    }
    open override func removeTarget(_ target: AnyObject) {
        super.removeTarget(target)
        self.whenRemove()
    }
    open override func removeBlock(_ identifier: String) {
        super.removeBlock(identifier)
        self.whenRemove()
    }
    open override func removeAllActions() {
        super.removeAllActions()
        self.whenRemove()
    }
    open override func sendActions(for parameter: Void) {
        self.lastSendTime = Date()
        super.sendActions(for: parameter)
    }
    deinit {
        self.cancelTimer()
    }
}
